import { Inject, Injectable } from '@nestjs/common';
import { RedisClientType } from 'redis';

@Injectable()
export class RedisService {
  @Inject('REDIS_CLIENT')
  private redisClient: RedisClientType;

  // 设置限时
  async setWithTTL(key: string, ttl: number) {
    await this.redisClient.expire(key, ttl);
  }

  // 字符串操作
  async get(key: string) {
    return await this.redisClient.get(key);
  }

  async set(key: string, value: string | number, ttl?: number) {
    await this.redisClient.set(key, value);

    if (ttl) {
      await this.redisClient.expire(key, ttl);
    }
  }

  async del(key: string) {
    await this.redisClient.del(key);
  }

  // 列表操作
  async rpush(key: string, ...values: string[]) {
    return await this.redisClient.rPush(key, values);
  }

  async lpush(key: string, ...values: string[]) {
    return await this.redisClient.lPush(key, values);
  }

  async lrange(key: string, start: number, stop: number) {
    return await this.redisClient.lRange(key, start, stop);
  }

  async llen(key: string) {
    return await this.redisClient.lLen(key);
  }

  async lrem(key: string, count: number, value: string) {
    return await this.redisClient.lRem(key, count, value);
  }

  // 获取指定索引的元素
  async lindex(key: string, index: number) {
    return await this.redisClient.lIndex(key, index);
  }

  // 设置指定索引的元素值
  async lset(key: string, index: number, value: string) {
    return await this.redisClient.lSet(key, index, value);
  }

  // 从列表左侧弹出元素
  async lpop(key: string) {
    return await this.redisClient.lPop(key);
  }

  // 从列表右侧弹出元素
  async rpop(key: string) {
    return await this.redisClient.rPop(key);
  }

  async ltrim(key: string, start: number, stop: number) {
    return await this.redisClient.lTrim(key, start, stop);
  }

  async onModuleDestroy() {
    await this.redisClient.quit();
  }

  async incr(key: string) {
    return await this.redisClient.incr(key);
  }

  async decr(key: string) {
    return await this.redisClient.decr(key);
  }

  // 删除所有匹配前缀的键
  async delByPattern(pattern: string) {
    const keys: string[] = [];
    let cursor = 0;

    do {
      const result = await this.redisClient.scan(cursor.toString(), {
        MATCH: pattern,
        COUNT: 100,
      });
      cursor = parseInt(result.cursor);
      keys.push(...result.keys);
    } while (cursor !== 0);

    if (keys.length > 0) {
      await this.redisClient.del(keys);
    }

    return keys.length;
  }
}
